package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author waker
 * @since 2025-10-25
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    @Autowired
    private IInteractionReplyService interactionReplyService;
    private final InteractionReplyMapper interactionReplyMapper;
    private final UserClient userClient;
    private final CourseClient courseClient;
    private final SearchClient searchClient;
    private final CatalogueClient catalogueClient;
    private final CategoryClient categoryClient;
    private final CategoryCache categoryCache;

    /**
     * 1. 新增互动问题
     *
     * @param questionFormDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionFormDTO) {
        // 1、文本审核(问题内容合规性检测) TODO

        // 2、数据拷贝
        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionFormDTO, InteractionQuestion.class);

        // 3、补充用户ID
        interactionQuestion.setUserId(UserContext.getUser());

        // 4. 新增
        save(interactionQuestion);
    }

    /**
     * 2. 修改互动问题
     *
     * @param id
     * @param questionFormDTO
     */
    @Override
    public void updateQuestion(Long id, QuestionFormDTO questionFormDTO) {
        // 1、查询旧数据
        InteractionQuestion question = getById(id);
        if (ObjectUtil.isEmpty(question)) {
            throw new BadRequestException("要修改的互动问题不存在！");
        }
        if (!ObjectUtil.equal(question.getUserId(), UserContext.getUser())) {
            throw new BadRequestException("没有权限修改该互动问题！");
        }

        // 2、数据拷贝
        BeanUtils.copyProperties(questionFormDTO, question);

        // 3、修改
        boolean result = updateById(question);
        if (!result) {
            log.error("修改互动问题失败！");
        }
    }

    /**
     * 3. 分页查询互动问题列表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionVO> pageQuery(QuestionPageQuery query) {
        // 1. 参数校验
        Long courseId = query.getCourseId();
        Long sectionId = query.getSectionId();
        if (ObjectUtil.isEmpty(courseId) && ObjectUtil.isEmpty(sectionId)) {
            throw new BadRequestException("课程ID和小节ID不能同时为空！");
        }

        // 2. 分页查询 select * from interaction_question where course_id = ?
        // and section_id = ? and user_id = ? and hidden = 0 order by create_time desc limit ?,?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .eq(query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(ObjectUtil.isNotEmpty(courseId), InteractionQuestion::getCourseId, courseId)
                .eq(ObjectUtil.isNotEmpty(sectionId), InteractionQuestion::getSectionId, sectionId)
                .eq(InteractionQuestion::getHidden, false)
                .select(InteractionQuestion.class, tableFieldInfo -> ObjectUtil.notEqual(tableFieldInfo.getColumn(), "description"))
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtil.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3. 补充信息查询： 提问者信息（非匿名）、查询最近一次回答信息（最近一次回答内容、最近回答者ID）
        // 3.1 获取提问用户ID/最近一次回答ID，收集为set集合
//        Set<Long> userIds = records.stream().filter(q-> !q.getAnonymity()).map(InteractionQuestion::getUserId).collect(Collectors.toSet());
/*        Set<Long> userIds = CollStreamUtil.toSet(records, InteractionQuestion::getUserId);
        Set<Long> lastAnswerIds = records.stream().map(InteractionQuestion::getLatestAnswerId).collect(Collectors.toSet());*/
        Set<Long> userIds = new HashSet<>(records.size());
        Set<Long> lastAnswerIds = new HashSet<>(records.size());
        Set<Long> questionIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            questionIds.add(record.getId());
            lastAnswerIds.add(record.getLatestAnswerId());
        }
        lastAnswerIds.remove(null);

        // 3.2 根据最近一次回答ID集合，查询最近一次回答信息，封装为Map(k: 最近一次回答ID , v: 最近一次回答对象)
        List<InteractionReply> lastReplyList = new ArrayList<>(lastAnswerIds.size());
        if (ObjectUtil.isNotEmpty(lastAnswerIds)) {
            lastReplyList = interactionReplyService.listByIds(lastAnswerIds);
        }
//        Map<Long, InteractionReply> lastReplyMap = CollStreamUtil.toMap(lastReplyList, InteractionReply::getId, Function.identity());
/*        Map<Long, InteractionQuestion> replyMap = CollStreamUtil.toIdentityMap(records, InteractionQuestion::getLatestAnswerId);
        Set<Long> replyUserIds = lastReplyList.stream().filter(r -> !r.getAnonymity()).map(r -> r.getUserId()).collect(Collectors.toSet());
        userIds.addAll(replyUserIds);*/

        Map<Long, InteractionReply> replyMap = new HashMap<>(lastReplyList.size());
        if (ObjectUtil.isNotEmpty(lastReplyList)) {
            for (InteractionReply reply : lastReplyList) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        // 3.3 合并提问者ID集合和最近一次回答者ID集合，查询提问者用户信息，封装为Map(k: 用户ID , v: 用户信息对象)
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userInfoMap = new HashMap<>(userInfoList.size());
        if (ObjectUtil.isNotEmpty(userInfoList)) {
            userInfoMap = CollStreamUtil.toIdentityMap(userInfoList, UserDTO::getId);
        }

        // 优化： 只显示未被隐藏的回答 查询未被隐藏的回答
        QueryWrapper<InteractionReply> replyQueryWrapper = new QueryWrapper<>();
        replyQueryWrapper.select("question_id,count(1) num")
                .eq("hidden", false)
                .eq("answer_id",0)
                .in("question_id", questionIds)
                .groupBy("question_id");

        List<Map<String, Object>> unHideReplyCountListMap = interactionReplyMapper.selectMaps(replyQueryWrapper);
        Map<Long, Integer> unHideReplyCountMap = new HashMap<>(unHideReplyCountListMap.size());
        if (ObjectUtil.isNotEmpty(unHideReplyCountListMap)){
            unHideReplyCountMap = unHideReplyCountListMap.stream().collect(Collectors.toMap(
                    map -> Long.parseLong(map.get("question_id").toString()),
                    map -> Integer.parseInt(map.get("num").toString())));
        }

        // 4. 循环遍历当前页码分页数据，封装vo集合
        List<QuestionVO> questionVOS = new ArrayList<>(records.size());
        for (InteractionQuestion question : records) {
            // 4.1 将po转为vo
            QuestionVO questionVO = new QuestionVO();
            BeanUtils.copyProperties(question, questionVO);

            // 4.2 补充提问者信息(昵称、头像)
            UserDTO userInfo = userInfoMap.get(question.getUserId());
            if (!question.getAnonymity()) {
                if (ObjectUtil.isNotEmpty(userInfo)) {
                    questionVO.setUserName(userInfo.getName());
                    questionVO.setUserIcon(userInfo.getIcon());
                }
            }

            // 4.3 补充最近一次回答的信息(最近一次回答内容、最近一次回答者昵称)
            InteractionReply lastReply = replyMap.get(question.getLatestAnswerId());
            if (ObjectUtil.isNotEmpty(lastReply)) {
                questionVO.setLatestReplyContent(lastReply.getContent());
                if (!lastReply.getAnonymity()) {
                    UserDTO answerUserInfo = userInfoMap.get(lastReply.getUserId());
                    if (ObjectUtil.isNotEmpty(answerUserInfo)) {
                        questionVO.setLatestReplyUser(answerUserInfo.getName());
                    }
                }
            }

            // 4.4 优化：只显示未被隐藏的回答数量
            questionVO.setAnswerTimes(unHideReplyCountMap.getOrDefault(question.getId(), 0));

            // 4.4 添加到vo到集合
            questionVOS.add(questionVO);
        }

        // 5. 封装分页结果返回
        return PageDTO.of(pageResult, questionVOS);
    }

    /**
     * 4. 根据id查询问题详情
     *
     * @param id
     * @return
     */
    @Override
    public QuestionVO queryQuestionById(Long id) {
        // 1. 根据id查询问题详情
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question) || question.getHidden()) {
            return null;
        }

        // 2. 补全提问用户信息（用户昵称/头像）
        QuestionVO questionVO = BeanUtils.toBean(question, QuestionVO.class);
        if (!question.getAnonymity()) {
            UserDTO userInfo = userClient.queryUserById(question.getUserId());
            if (ObjectUtil.isNotEmpty(userInfo)) {
                questionVO.setUserName(userInfo.getName());
                questionVO.setUserIcon(userInfo.getIcon());
            }
        }

        // 3. 封装vo返回
        return questionVO;
    }

    /**
     * 5. 删除我的问题
     *
     * @param id
     */
    @Override
    public void deleteQuestionById(Long id) {
        // 1. 获取当前用户ID
        Long userId = UserContext.getUser();

        // 2. 判断问题是否存在
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question)) {
            return;
        }

        // 3. 判断问题是否是当前用户提问，不是则报错
        if (!userId.equals(question.getUserId())) {
            throw new BadRequestException("此问题非您提问，无法删除！");
        }

        // 4. 是，删除问题并删除问题下的回答和评论
        boolean result = removeById(id);
        if (result) {
            interactionReplyService.lambdaUpdate()
                    .eq(InteractionReply::getQuestionId, id)
                    .remove();
        }

    }

    /**
     * 6. 管理端-分页查询互动问题列表
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery query) {
        // 1. 远程调用es,根据课程名称，得到课程ID集合
        List<Long> courseIds = new ArrayList<>();
        if (StrUtil.isNotBlank(query.getCourseName())) {
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (ObjectUtil.isEmpty(courseIds)) {
                return PageDTO.empty(0L, 0L);
            }
        }

        // 2. 分页查询问题列表 select * from interaction_question where course_id = ? and status = ?
        // where create_time >= ? and create_time <= ? and ? limit ?, ?
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .in(ObjectUtil.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtil.isNotEmpty(query.getStatus()),InteractionQuestion::getStatus, query.getStatus())
                .le(ObjectUtil.isNotEmpty(query.getEndTime()), InteractionQuestion::getCreateTime, query.getEndTime())
                .ge(ObjectUtil.isNotEmpty(query.getBeginTime()), InteractionQuestion::getCreateTime, query.getBeginTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtil.isEmpty(records)){
            return PageDTO.empty(pageResult);
        }

        // 3. 补充信息查询（章节数据、课程数据、用户数据）
        // 3.1 收集各种业务的ID集合
        Set<Long> userIdSet = new HashSet<>(records.size());
        Set<Long> courseIdSet = new HashSet<>(records.size());
        Set<Long> chapterIdSet = new HashSet<>(records.size());
        for (InteractionQuestion question : records){
            userIdSet.add(question.getUserId());
            courseIdSet.add(question.getCourseId());
            chapterIdSet.add(question.getChapterId());
            chapterIdSet.add(question.getSectionId());
        }

        // 3.2 根据用户ID集合查询用户信息,转为Map(Map -> 用户ID:用户昵称)
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIdSet);
        Map<Long, String> userInfoMap = new HashMap<>(userIdSet.size());
        if (ObjectUtil.isNotEmpty(userInfoList)){
            userInfoMap = CollStreamUtil.toMap(userInfoList, UserDTO::getId, UserDTO::getName);
        }

        // 3.3 根据课程ID集合查询课程信息,转为Map(Map -> 课程ID:课程对象)
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(courseIdSet);
        Map<Long, CourseSimpleInfoDTO> courseInfoMap = new HashMap<>(courseIdSet.size());
        if (ObjectUtil.isNotEmpty(courseInfoList)){
            courseInfoMap = CollStreamUtil.toIdentityMap(courseInfoList, CourseSimpleInfoDTO::getId);
        }

        // 3.4 根据章节ID集合查询章节信息(目录信息),转为Map(Map -> 章节ID:章节名称)
        List<CataSimpleInfoDTO> cataInfoList = catalogueClient.batchQueryCatalogue(chapterIdSet);
        Map<Long, String> cataInfoMap = new HashMap<>(chapterIdSet.size());
        if (ObjectUtil.isNotEmpty(cataInfoList)){
            cataInfoMap = CollStreamUtil.toMap(cataInfoList, CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName);
        }

        // 4. 循环分页列表数据，封装vo集合
        List<QuestionAdminVO> voList = new ArrayList<>(records.size());

        // 查询分类数据
       /* List<CategoryBasicDTO> allOfOneLevel = categoryClient.getAllOfOneLevel();
        Map<Long, String> categoryMap = CollStreamUtil.toMap(allOfOneLevel, CategoryBasicDTO::getId, CategoryBasicDTO::getName);*/
        for (InteractionQuestion question : records) {
            // 4.1 属性拷贝，将po 转为 vo
            QuestionAdminVO vo = BeanUtils.toBean(question, QuestionAdminVO.class);

            // 4.2 补充章节名称
            vo.setChapterName(cataInfoMap.getOrDefault(question.getChapterId(),""));
            vo.setSectionName(cataInfoMap.getOrDefault(question.getSectionId(),""));

            // 4.3 填充提问者昵称
            vo.setUserName(userInfoMap.getOrDefault(question.getUserId(),""));

            // 4.4 填充课程名称和 三级分类信息
            CourseSimpleInfoDTO courseInfo = courseInfoMap.get(question.getCourseId());
            if (ObjectUtil.isNotEmpty(courseInfo)){
                vo.setCourseName(courseInfo.getName());
                // 已知三级课程分类ID -> 三级分类名称拼接字符串：一级分类/二级分类/三级分类
/*                String firstCateName = categoryMap.get(courseInfo.getFirstCateId());
                String secondCateName = categoryMap.get(courseInfo.getSecondCateId());
                String thirdCateName = categoryMap.get(courseInfo.getThirdCateId());
                String categoryName = List.of(firstCateName, secondCateName, thirdCateName).stream().collect(Collectors.joining("/"));*/
//                vo.setCategoryName(String.format("%s/%s/%s", firstCateName, secondCateName, thirdCateName));
                // 使用caffeine缓存查询
                String categoryName = categoryCache.getCategoryNames(courseInfo.getCategoryIds());
                vo.setCategoryName(categoryName);
            }

            // 4.5 添加至voList
            voList.add(vo);
        }

        // 5. 封装分页结果并返回
        return PageDTO.of(pageResult, voList);
    }

    /**
     * 7. 管理端-显示或隐藏问题
     * @param id
     * @param hidden
     */
    @Override
    public void displayOrHideQuestion(Long id, boolean hidden) {
        // 1. 查询问题
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question)){
            throw new BadRequestException("问题不存在！");
        }
        // 2. 修改问题状态
        question.setHidden(hidden);
        this.updateById(question);

        // 3. 修改问题下所有回复的状态 TODO
    }

    /**
     * 8. 管理端-根据id查询问题详情
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO adminQueryQuestionById(Long id) {
        // 1. 查询问题
        InteractionQuestion question = this.getById(id);
        if (ObjectUtil.isEmpty(question)){
            throw new BadRequestException("问题不存在！");
        }
        // 2. 拷贝
        QuestionAdminVO vo = BeanUtils.toBean(question, QuestionAdminVO.class);
        // 3. 补全缺少的信息
        // 3.1 补全提问者信息
        UserDTO userInfo = userClient.queryUserById(question.getUserId());
        if (ObjectUtil.isNotEmpty(userInfo)){
            vo.setUserName(userInfo.getName());
            vo.setUserIcon(userInfo.getIcon());
        }

        // 3.2 补全课程信息
        CourseFullInfoDTO courseInfo = courseClient.getCourseInfoById(question.getCourseId(), true, true);
        if (ObjectUtil.isNotEmpty(courseInfo)){
            vo.setCourseName(courseInfo.getName());
        }

        // 3.3 补全章节信息
        List<Long> chapterIds = List.of(question.getChapterId(), question.getSectionId());
        List<CataSimpleInfoDTO> catalogueInfoList = catalogueClient.batchQueryCatalogue(chapterIds);
        if (ObjectUtil.isNotEmpty(catalogueInfoList)){
            Map<Long, String> cateMap = CollStreamUtil.toMap(catalogueInfoList, CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName);
            vo.setChapterName(cateMap.getOrDefault(question.getChapterId(),""));
            vo.setSectionName(cateMap.getOrDefault(question.getSectionId(),""));
        }

        // 3.4 补全分类信息
        List<Long> categoryIds = courseInfo.getCategoryIds();
        String categoryName = categoryCache.getCategoryNames(categoryIds);
        vo.setCategoryName(categoryName);

        // 3.5 补全教师信息
        List<Long> teacherIds = courseInfo.getTeacherIds();
        List<UserDTO> teacherInfoList = userClient.queryUserByIds(teacherIds);
        vo.setTeacherName(teacherInfoList.stream().map(UserDTO::getName).collect(Collectors.joining(",")));

        // 查看问题详情后设置为已查看
        vo.setStatus(1);
        return vo;
    }
}
